package com.jiaz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jiaz.entity.CheckIn;
import com.jiaz.entity.Postion;
import com.jiaz.mapper.CheckInMapper;
import com.jiaz.mapper.PostionMapper;
import com.jiaz.service.PostionService;
import com.jiaz.untils.ResponseBean;
import com.jiaz.untils.constant.VarConstant;
import com.jiaz.vo.QueryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @author jiajiazi
 * @version 1.0
 * @date 2022/4/24 16:17
 */
@Service
public class PostionServiceImpl implements PostionService {

    @Autowired
    private PostionMapper postionMapper;
    @Autowired
    private CheckInMapper checkInMapper;


    Map<String, Double> postionBounder;

    {
        postionBounder = new HashMap<>();
        postionBounder.put("maxlat", 40.9883317);
        postionBounder.put("minlat", 40.5508525);
        postionBounder.put("maxlon", -73.6838252);
        postionBounder.put("minlon", -74.2747664);
    }

    @Override
    public ResponseBean getPostionList(QueryVo queryVo) {
        if (ObjectUtils.isEmpty(queryVo)) {
            return ResponseBean.error(4008, "参数错误(空值)");
        }
        if (queryVo.getPageNum() == null) {
            queryVo.setPageNum(VarConstant.PAGE_NUM);
        }
        if (queryVo.getPageSize() == null) {
            queryVo.setPageSize(VarConstant.PAGE_SIZE);
        }
        QueryWrapper<Postion> queryWrapper = null;
        String key = queryVo.getKey();
        if (StringUtils.hasLength(key)) {
            queryWrapper = new QueryWrapper<>();
            queryWrapper.and(q -> q.like("id", key).or().like("venue_category", key));
        }
        Page<Postion> page = new Page<>(queryVo.getPageNum(), queryVo.getPageSize());
        Page<Postion> postionPage = postionMapper.selectPage(page, queryWrapper);
        return ResponseBean.success(postionPage);
    }

    /**
     * 1度大致110km，误差使用+/- 0.02
     *
     * @param lat
     * @param lon
     * @return
     */
    @Override
    public ResponseBean getClosePostionList(double lat, double lon) {
        if (postionBounder == null) {
            postionBounder = postionMapper.getPostionBounder();
        }
        Double minlat = postionBounder.get("minlat");
        Double maxlat = postionBounder.get("maxlat");
        Double minlon = postionBounder.get("minlon");
        Double maxlon = postionBounder.get("maxlon");
        if (minlat <= lat && lat <= maxlat &&
                minlon <= lon && lon <= maxlon) {
            QueryWrapper<Postion> queryWrapper = new QueryWrapper<>();
            queryWrapper.ge("lat", lat - VarConstant.POSTION_PATTREN_DISTANT)
                    .ge("lon", lon - VarConstant.POSTION_PATTREN_DISTANT)
                    .le("lat", lat + VarConstant.POSTION_PATTREN_DISTANT)
                    .le("lon", lon + VarConstant.POSTION_PATTREN_DISTANT);
            List<Postion> postions = postionMapper.selectList(queryWrapper);
            if (postions.size() <= VarConstant.POSTION_DISTANT_NUM) {
                return ResponseBean.success(postions);
            }
            postions.sort(new Comparator<Postion>() {
                @Override
                public int compare(Postion o1, Postion o2) {
                    double d = Math.pow(o1.getLat() - lat, 2) + Math.pow(o1.getLon() - lon, 2) - Math.pow(o2.getLat() - lat, 2) - Math.pow(o2.getLon() - lon, 2);
                    if (d == 0) {
                        return 0;
                    } else if (d > 0) {
                        return 1;
                    } else {
                        return -1;
                    }
                }
            });
            return ResponseBean.success(postions.subList(0, VarConstant.POSTION_DISTANT_NUM));
        } else {
            return ResponseBean.error(40007, String.format("纬度[%s~%s],经度[%s~%s]", minlat, maxlat, minlon, maxlon));
        }
    }

    @Override
    public ResponseBean getPostionFreq(Double lat, Double lon, Integer userId) {
        ArrayList<Double[]> postions = new ArrayList<>();
        HashMap<String, Integer> freqMap = new HashMap<>();
        HashMap<String, Object> resMap = new HashMap<>();
        if (userId == null || userId == 0) {
            // 全部
            QueryWrapper<Postion> queryWrapper = new QueryWrapper<>();
            queryWrapper.ge("lat", lat - VarConstant.POSTION_FREQ_DISTANT)
                    .ge("lon", lon - VarConstant.POSTION_FREQ_DISTANT)
                    .le("lat", lat + VarConstant.POSTION_FREQ_DISTANT)
                    .le("lon", lon + VarConstant.POSTION_FREQ_DISTANT);
            List<Postion> postionList = postionMapper.selectList(queryWrapper);
            if (postionList == null || postionList.size() == 0) {
                return ResponseBean.error(40009, "获取数据为空");
            }
            for (Postion postion : postionList) {
                postions.add(new Double[]{postion.getLat(), postion.getLon()});
                freqMap.put(postion.getLat() + ":" + postion.getLon(), postion.getFrequency());
            }
        } else {
            List<Map<String, Object>> currentUserPostionFreq = checkInMapper.getCurrent_User_Postion_Freq(lat, lon, userId);
            if (currentUserPostionFreq == null || currentUserPostionFreq.size() == 0) {
                return ResponseBean.error(40009, "获取数据为空");
            }
            for (Map<String, Object> smp : currentUserPostionFreq) {
                postions.add(new Double[]{Double.parseDouble(smp.get("lat").toString()), Double.parseDouble(smp.get("lon").toString())});
                freqMap.put(smp.get("lat") + ":" + smp.get("lon"), Math.toIntExact((Long) smp.get("freq")));
            }
        }
        resMap.put("postions", postions);
        resMap.put("freq", freqMap);

        return ResponseBean.success(resMap);
    }

    @Override
    public ResponseBean getAllHeatMap() {
        QueryWrapper<Postion> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("lon", "lat", "frequency");
        List<Postion> postionList = postionMapper.selectList(queryWrapper);
        if (postionList == null || postionList.size() == 0) {
            return ResponseBean.error(40009, "获取数据为空");
        }
        ArrayList<double[]> resList = new ArrayList<>();
        for (Postion postion : postionList) {
            resList.add(new double[]{postion.getLon(), postion.getLat(), postion.getFrequency()});
        }
        return ResponseBean.success(resList);
    }

}
